package com.irdstudio.efp.esb.api.service.yed.apply;

import com.alibaba.fastjson.JSON;
import com.irdstudio.basic.framework.core.constant.BaseConstant;
import com.irdstudio.basic.framework.core.constant.EsbRetCodeStandard;
import com.irdstudio.basic.framework.core.constant.SDicToLocalConstant;
import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.basic.framework.core.util.DateUtility;
import com.irdstudio.basic.framework.core.util.sdic.SDicToLocal;
import com.irdstudio.efp.basic.framework.mq.client.producer.MQProducerMessageClient;
import com.irdstudio.efp.basic.framework.mq.constant.TagEnums;
import com.irdstudio.efp.basic.framework.mq.constant.TopicEnums;
import com.irdstudio.efp.console.service.facade.PrdInfoService;
import com.irdstudio.efp.console.service.facade.PubSysInfoService;
import com.irdstudio.efp.console.service.vo.PrdInfoVO;
import com.irdstudio.efp.console.service.vo.PrdInfoVOBuilder;
import com.irdstudio.efp.ctr.service.facade.CtrLoanContService;
import com.irdstudio.efp.cus.service.facade.CusIndivService;
import com.irdstudio.efp.cus.service.vo.CusIndivVO;
import com.irdstudio.efp.esb.api.rest.yed.req.YedApproveReqBean;
import com.irdstudio.efp.esb.api.service.common.repository.LmtRepository;
import com.irdstudio.efp.esb.api.service.common.repository.NlsRepository;
import com.irdstudio.efp.esb.common.constant.MsLoanConstant;
import com.irdstudio.efp.esb.common.server.req.EsbReqServiceBean;
import com.irdstudio.efp.limit.service.vo.LmtPrdContVO;
import com.irdstudio.efp.nls.common.constant.PrdAdaptedSoltEnums;
import com.irdstudio.efp.nls.common.constant.QueueTaskEnums;
import com.irdstudio.efp.nls.service.facade.yed.UpdateLmtPrdContService;
import com.irdstudio.efp.nls.service.common.rules.CertRule;
import com.irdstudio.efp.nls.service.common.rules.PhoneRule;
import com.irdstudio.efp.nls.service.common.rules.ValidateLmtPrdContRule;
import com.irdstudio.efp.nls.service.common.rules.ValidatePrdRule;
import com.irdstudio.efp.nls.service.common.rules.apply.*;
import com.irdstudio.efp.nls.service.common.rules.credit.HasCreditInfoRule;
import com.irdstudio.efp.nls.service.facade.NlsApplyInfoService;
import com.irdstudio.efp.nls.service.facade.queue.NlsProcessBizService;
import com.irdstudio.efp.nls.service.vo.NlsApplyInfoVO;
import com.irdstudio.efp.nls.service.vo.queue.NlsProcessBizVO;
import com.irdstudio.efp.nls.service.vo.sx.NlsCreditInfoVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Objects;
import java.util.Optional;


/**
 * 优e贷用信申请
 * author：zhangbf
 * date：20200728
 */
@Service("yedApplyService")
public class YedApplyService {

    private static Logger logger = LoggerFactory.getLogger(YedApplyService.class);

    public void initLoanApply(YedApproveReqBean yedApplyReqBean, EsbReqServiceBean esbReqServiceBean) throws BizException {
        try {
            NlsApplyInfoVO nlsApplyInfoVO = new NlsApplyInfoVO();
            PrdInfoVO product = getProduct(yedApplyReqBean.getPdCd());
            nlsApplyInfoVO.checkFor(new ValidatePrdRule(product));

            if(yedApplyReqBean.getLoanAmt().doubleValue()==0){
                throw new BizException(EsbRetCodeStandard.SJCLYC.getValue(), "优e贷用信申请金额为0，请修改！");
            }
            NlsApplyInfoVO selectNlsApplyInfo = nlsRepository.getNlsApplyInfoBySeq(yedApplyReqBean.getUseCrdtAppSrlNo());
            nlsApplyInfoVO.checkFor(new ApplySeqExistRule(selectNlsApplyInfo));
            NlsCreditInfoVO nlsCreditInfoVO = nlsRepository.getNlsCreditInfoBySeq(yedApplyReqBean.getCrAppSrlNo());
            nlsApplyInfoVO.checkFor(new HasCreditInfoRule(nlsCreditInfoVO));

            if(!nlsCreditInfoVO.getCertCode().equals(yedApplyReqBean.getIdentNo())){
                logger.error("优e贷用信申请的证件号码和授信申请的证件号码不一致：[{}]");
                throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "优e贷用信申请的证件号码和授信申请的证件号码不一致");
            }
            CusIndivVO cusIndivVO = new CusIndivVO();
            cusIndivVO.setCertCode(nlsCreditInfoVO.getCertCode());
            CusIndivVO queryCusIndivVO = cusIndivService.queryByCondition(cusIndivVO);
            String openday = pubSysInfoService.getOpenday(BaseConstant.SYS_ID_1001);
            nlsApplyInfoVO.checkFor(new GlobalSernoExistRule(nlsApplyInfoService.countInfosByGlobalSerno(esbReqServiceBean.getSysHead().getGlblSrlNo())));
            nlsApplyInfoVO.checkFor(new ValidateFormatDate(yedApplyReqBean.getLoanAppTm()));
            //优e贷不限制贷款期数，最大为36期
            nlsApplyInfoVO.checkFor(new YedApplyIsOverCreditApplyDateRule(nlsCreditInfoVO.getApplyDate(), Integer.parseInt(yedApplyReqBean.getLoanTrm()), openday, yedApplyReqBean.getUseCrdtAppSrlNo()));
            LmtPrdContVO lmtPrdContVO = lmtRepository.getActiveLmtPrdCont(nlsCreditInfoVO.getLmtApplySeq());
            nlsApplyInfoVO.checkFor(new PhoneRule(nlsCreditInfoVO.getIndivMobile()));
            nlsApplyInfoVO.checkFor(new CertRule(nlsCreditInfoVO.getCertCode()));
            nlsApplyInfoVO.checkFor(new CertEndDtRule(DateUtility.format8To10(queryCusIndivVO.getIndivIdExpDt()),pubSysInfoService.getOpenday(BaseConstant.SYS_ID_1001)));
            //优e贷有授信用信在途申请接口
            nlsApplyInfoVO.checkFor(new OnWayApplyRule(nlsRepository.getOnWayApply(yedApplyReqBean)));
            nlsApplyInfoVO.checkFor(new CreditNotPassRule(nlsCreditInfoVO));
            nlsApplyInfoVO.checkFor(new CreditPrdInfoIncorrectRule(nlsRepository.getNlsCreditInfoVO(yedApplyReqBean.getCrAppSrlNo()), yedApplyReqBean.getPdCd(), yedApplyReqBean.getLoanPdNm()));

            // 先注释掉校验用信申请流水号格式的代码，因为风控的挡板要有-b
            nlsApplyInfoVO.checkFor(new ValidateApplySeqRule(yedApplyReqBean.getUseCrdtAppSrlNo()));
            //优e贷授信阶段没有协议，有综合委托授权书
            nlsApplyInfoVO.checkFor(new ValidateLmtPrdContRule(lmtPrdContVO));
            nlsApplyInfoVO.checkFor(new LmtExpireRule(lmtPrdContVO.getExpireDate(), yedApplyReqBean.getUseCrdtAppSrlNo(),openday));
            //nlsApplyInfoVO.checkFor(new TheLastLoanDateAndLmtExpireDateRule(lmtPrdContVO.getSignDate(), yedApplyReqBean.getUseCrdtAppSrlNo(),openday,yedApplyReqBean.getLoanTrm()));
            //nlsApplyInfoVO.checkFor(new RepayMethodAndLoanTermRule(yedApplyReqBean.getRpymtMd(),yedApplyReqBean.getLoanTrm()));
            BigDecimal availAmt = (Objects.isNull(lmtPrdContVO.getAvailAmt()) ? nlsCreditInfoVO.getApproveAmt() : lmtPrdContVO.getAvailAmt());
            BigDecimal loanAmt = (Objects.isNull(yedApplyReqBean.getLoanAmt()) ? BigDecimal.ZERO : new BigDecimal(yedApplyReqBean.getLoanAmt()));
            nlsApplyInfoVO.checkFor(new ValidateAvailAmtAndLoanAmt(availAmt, loanAmt, yedApplyReqBean.getUseCrdtAppSrlNo()));
            //优e贷风控有此条规则，网贷无需校验，网贷校验不准
            //nlsApplyInfoVO.checkFor(new OverDueAccLoanRule(accLoanRepository.getAccLoanByCertTypeOrCode(nlsCreditInfoVO.getCertType(), nlsCreditInfoVO.getCertCode())));

            if(StringUtils.isBlank(yedApplyReqBean.getDistrCardNo())){
                logger.error("优e贷用信申请贷款账号不能为空：[{}]");
                throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "优e贷用信申请贷款账号不能为空");
            }
            if(StringUtils.isBlank(yedApplyReqBean.getRpymtCardNo())){
                logger.error("优e贷用信申请还款卡号不能为空：[{}]");
                throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "优e贷用信申请还款卡号不能为空");
            }
            if(!"FB03".equals(yedApplyReqBean.getRpymtMd())){
                logger.error("优e贷还款方式为等额本息(FB03)：[{}]");
                throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "优e贷还款方式为等额本息(FB03)");
            }
            //caoxin:插入的时候需要双重校验（如果有流量同时进到这里就会有问题后续修改）
            nlsApplyInfoVO = insertNlsApplyInfo(esbReqServiceBean, yedApplyReqBean, nlsCreditInfoVO);
            insertNlsProcessBiz(yedApplyReqBean.getUseCrdtAppSrlNo(), nlsCreditInfoVO);
            yedUpdateLmtPrdContService.updateLmtPro(nlsCreditInfoVO.getLmtApplySeq(), nlsApplyInfoVO.getApplySeq());


            /*String signDate = lmtPrdContVO.getSignDate();
            NlsApplyInfoVO dateNlsApplyVO = Optional.ofNullable(nlsApplyInfoService.queryLatestNlsApplyInfo(nlsApplyInfoVO)).orElseGet(NlsApplyInfoVO::new);
            if (!isOver30days(signDate,openday) || !isLastestLoanOver30days(dateNlsApplyVO.getApplyDate(),openday)) {
                updateNlsApplyInfo(nlsApplyInfoVO);
                insertLoanCtrContract(nlsApplyInfoVO, nlsCreditInfoVO, lmtPrdContVO);
                sendMessageToMq(nlsApplyInfoVO, "-2");
            } else*/
            sendMessageToMq(nlsApplyInfoVO, "-1");



        } catch (BizException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
            throw e;
        } catch (UnsupportedEncodingException e) {
            logger.error("优e贷用信申请发送消息到mq出现异常：[{}]", e.getMessage());
            e.printStackTrace();
            throw new BizException(EsbRetCodeStandard.WFJKYWGZ.getValue(), "优e贷用信申请发送消息到mq出现异常");
        } catch (Exception e) {
            logger.error("优e贷用信申请业务处理出现异常：[{}]", e.getMessage());
            e.printStackTrace();
            throw new BizException(EsbRetCodeStandard.WFJKYWGZ.getValue(), e.getMessage());
        } finally {
        }
    }

    private void updateNlsApplyInfo(NlsApplyInfoVO nlsApplyInfoVO) throws Exception {
        nlsApplyInfoVO.setSoltStage(PrdAdaptedSoltEnums.PsdSoltStageEnum.LETTER_BACK.getVALUE());
        //nlsApplyInfoVO.setFlowStatus(FLOW_STATUS_3);
        int result = nlsApplyInfoService.updateByPk(nlsApplyInfoVO);
        if (result != 1) {
            logger.error("优e贷用信申请 更新用信申请信息失败！");
            throw new BizException(EsbRetCodeStandard.YWLJCLYC.getValue(), "优e贷用信申请 更新用信申请信息失败！");
        }
    }

    private void sendMessageToMq(NlsApplyInfoVO nlsApplyInfoVO, String prefix) throws UnsupportedEncodingException {
        producerService.sendMsg(new Message(TopicEnums.YED_QUEUE_TASK_TOPIC.getTopicId(), TagEnums.YED_TAG_QUEUE_TASK.getTagId(), nlsApplyInfoVO.getApplySeq() + prefix,
                JSON.toJSONString(nlsApplyInfoVO).getBytes("UTF-8")));
    }

    private boolean isOver30days(String signDate,String openDay) throws BizException {
        return DateUtility.compareToDate(openDay, DateUtility.ADD_DAY(signDate, 30)) > 0;
    }

    private boolean isLastestLoanOver30days(String lastestDay, String openDay) throws BizException {
        if (Objects.isNull(lastestDay)) {
            return true;
        }
        return DateUtility.compareToDate(openDay, DateUtility.ADD_DAY(lastestDay, 30)) > 0;
    }

    /***
     * 插入网贷申请基本信息
     */
    private NlsApplyInfoVO insertNlsApplyInfo(EsbReqServiceBean esbReqServiceBean, YedApproveReqBean yedApplyReqBean, NlsCreditInfoVO nlsCreditInfoVO) throws Exception {
        NlsApplyInfoVO nlsApplyInfoVO = new NlsApplyInfoVO();
        /************************************************ 网贷申请基本信息表数据来源于【渠道端】字段  ********************************************** start */
        // 流水号
        nlsApplyInfoVO.setApplySeq(yedApplyReqBean.getUseCrdtAppSrlNo());
        // 客户名称
        nlsApplyInfoVO.setCusName(nlsCreditInfoVO.getCusName());
        // 证件类型
        nlsApplyInfoVO.setCertType(SDicToLocal.getLocalSysDicVal(SDicToLocalConstant.CERT_TYPE_SED, nlsCreditInfoVO.getCertType()));
        // 证件号码
        nlsApplyInfoVO.setCertCode(nlsCreditInfoVO.getCertCode());
        // 证件到期日
        nlsApplyInfoVO.setIndivIdExpDt(nlsCreditInfoVO.getCertEndDt());
        // 手机号码
        nlsApplyInfoVO.setMobile(nlsCreditInfoVO.getIndivMobile());
        // 申请时间
        nlsApplyInfoVO.setApplyTime(DateUtility.getCurrTime());
        // 贷款金额
        nlsApplyInfoVO.setApplyAmt(new BigDecimal(yedApplyReqBean.getLoanAmt()).setScale(2,BigDecimal.ROUND_HALF_UP));
        // 贷款期限
        nlsApplyInfoVO.setLoanTerm(yedApplyReqBean.getLoanTrm());
        // 期限类型
        nlsApplyInfoVO.setLoanTermType(SDicToLocal.getLocalSysDicVal(SDicToLocalConstant.TERM_TYPE, yedApplyReqBean.getLoanTrmTp()));
        //借款用途
        nlsApplyInfoVO.setLoanPurpose(Objects.nonNull(yedApplyReqBean.getLoanPps()) ? yedApplyReqBean.getLoanPps() : nlsCreditInfoVO.getLoanUseType());
        // 产品id
        nlsApplyInfoVO.setPrdId(yedApplyReqBean.getPdCd());
        // 产品代码
        nlsApplyInfoVO.setPrdCode(yedApplyReqBean.getPdCd());
        // 产品名称
        nlsApplyInfoVO.setPrdName(yedApplyReqBean.getLoanPdNm());
        // 币种
        nlsApplyInfoVO.setLoanCcy(SDicToLocal.getLocalSysDicVal(SDicToLocalConstant.CURRENCY, yedApplyReqBean.getCcy()));
        // 贷款利率
        nlsApplyInfoVO.setLoanRate(new BigDecimal(yedApplyReqBean.getLoanIntRt()));
        // 还款方式
        nlsApplyInfoVO.setRepayMethod(SDicToLocal.getLocalSysDicVal(SDicToLocalConstant.REPAY_WAY, yedApplyReqBean.getRpymtMd()));
        // 渠道
        nlsApplyInfoVO.setChannelNo(yedApplyReqBean.getChanFlg());
        // 授信流水号
        nlsApplyInfoVO.setLmtApplySeq(yedApplyReqBean.getCrAppSrlNo());
        // 放款卡号
        nlsApplyInfoVO.setDnAccount(StringUtils.isNotBlank(yedApplyReqBean.getDistrCardNo())?yedApplyReqBean.getDistrCardNo(): nlsCreditInfoVO.getDnAccount());
        // 还款卡号
        nlsApplyInfoVO.setRecvAcctNo(StringUtils.isNotBlank(yedApplyReqBean.getRpymtCardNo())?yedApplyReqBean.getRpymtCardNo(): nlsCreditInfoVO.getRecvAccount());
        // 还款周期
        nlsApplyInfoVO.setRepaymentPeriod(yedApplyReqBean.getRpymtCyc());
        // 还款周期单位
        nlsApplyInfoVO.setRepaymentPeriodType(SDicToLocal.getLocalSysDicVal(SDicToLocalConstant.TERM_TYPE, yedApplyReqBean.getRpymtCycUnit()));
        // 全局流水号
        nlsApplyInfoVO.setGlobalSerno(esbReqServiceBean.getSysHead().getGlblSrlNo());
        // 平台ID
        nlsApplyInfoVO.setPlatfmId(esbReqServiceBean.getSysHead().getPlafmID());
        // 平台用户ID
        nlsApplyInfoVO.setPlatfmUsrID(esbReqServiceBean.getSysHead().getPlafmUsrID());
        // 银行行号
        nlsApplyInfoVO.setBankId(yedApplyReqBean.getBnkNo());
        // 银行名称
        nlsApplyInfoVO.setBankName(yedApplyReqBean.getBnkNm());
        /************************************************ 网贷申请基本信息表数据来源于【渠道端】字段  ********************************************** end   */


        /**------------------- 网贷申请基本信息表数据来源于【本地授信申请信息表】字段 --------------- start */
        // 客户id
        nlsApplyInfoVO.setCusId(nlsCreditInfoVO.getCusId());
        //网贷经办人
        nlsApplyInfoVO.setNlsOperUserid(nlsCreditInfoVO.getNlsOperUserid());
        //网贷经办机构
        nlsApplyInfoVO.setNlsOperOrgid(nlsCreditInfoVO.getNlsOperOrgid());
        /**------------------- 网贷申请基本信息表数据来源于【本地授信申请信息表】字段 --------------- end   */

        /*********  网贷申请基本信息表数据来源于【其他】************ start */
        // 申请日期  = 营业日期
        nlsApplyInfoVO.setApplyDate(pubSysInfoService.getOpenday(BaseConstant.SYS_ID_1001));
        // 网贷申请状态---处理中
        nlsApplyInfoVO.setNlsApplyState(MsLoanConstant.NlsApplyStateEnum.APPR.VALUE);
        // 放款状态  = 待放款
        nlsApplyInfoVO.setDnSts(BaseConstant.DN_STS_3);
        // 用信插槽阶段
        nlsApplyInfoVO.setSoltStage(PrdAdaptedSoltEnums.PsdSoltStageEnum.LETTER_APPLY.getVALUE());
        // 创建人（直接插值）
        nlsApplyInfoVO.setCreateUser(BaseConstant.ADMIN);
        // 创建时间
        nlsApplyInfoVO.setCreateTime(DateUtility.getCurrAppDateTimeString());
        // 最后修改人（ 直接插值）
        nlsApplyInfoVO.setLastModifyUser(BaseConstant.ADMIN);
        // 最后修改时间
        nlsApplyInfoVO.setLastModifyTime(DateUtility.getCurrAppDateTimeString());
        // 流程状态
        //nlsApplyInfoVO.setFlowStatus(NlsApplyFlowStatus.FLOW_STATUS_1);
        /*********  网贷申请基本信息表数据来源于【其他】************ end   */
        int result = 0;
        try {
            result = nlsApplyInfoService.insertNlsApplyInfo(nlsApplyInfoVO);
            if (result != 1) {
                throw new BizException(EsbRetCodeStandard.YWLJCLYC.getValue(), "插入用信申请信息失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return nlsApplyInfoVO;
    }

    private void insertNlsProcessBiz(String applSeq, NlsCreditInfoVO nlsCreditInfoVO) throws BizException {
        NlsProcessBizVO inNlsProcessBizVo = new NlsProcessBizVO();
        // 申请流水号
        inNlsProcessBizVo.setApplySeq(applSeq);
        // 客户编号
        inNlsProcessBizVo.setCusId(nlsCreditInfoVO.getCusId());
        // 客户名称
        inNlsProcessBizVo.setCusName(nlsCreditInfoVO.getCusName());
        // 产品ID
        inNlsProcessBizVo.setPrdId(nlsCreditInfoVO.getPrdId());
        // 产品代码
        inNlsProcessBizVo.setPrdCode(nlsCreditInfoVO.getPrdId());
        inNlsProcessBizVo.setPrdName(nlsCreditInfoVO.getPrdName());// 产品名称
        inNlsProcessBizVo.setHangTimes(QueueTaskEnums.QueueHangTimesEnum.INITIALIZE.getTimes());
        inNlsProcessBizVo.setQueueTaskState(QueueTaskEnums.QueueTaskStateEnum.EXECUTORY.getCode());
        // 创建时间
        inNlsProcessBizVo.setCreateTime(DateUtility.getCurrAppDateTimeString());
        // 最后修改时间
        inNlsProcessBizVo.setLastModifyTime(DateUtility.getCurrAppDateTimeString());
        // 创建日期
        inNlsProcessBizVo.setCreateDate(DateUtility.getCurrAppDateStr());
        int num = nlsProcessBizService.insertNlsProcessBiz(inNlsProcessBizVo);
        if (num < 0) {
            throw new BizException(EsbRetCodeStandard.SJCLYC.getValue(), "插入网贷业务过程表异常!");
        }
    }

    private void insertLoanCtrContract(NlsApplyInfoVO nlsApplyInfoVO, NlsCreditInfoVO nlsCreditInfoVO, LmtPrdContVO lmtPrdContVO) throws BizException {
        nlsRepository.insertLoanCtrContract(nlsApplyInfoVO, nlsCreditInfoVO, lmtPrdContVO);
    }

    @Autowired
    @Qualifier("prdInfoService")
    private PrdInfoService prdInfoService;
    private PrdInfoVO getProduct(String prdId) {
        return Optional.ofNullable(prdInfoService.queryLastPrdInfo(PrdInfoVOBuilder.aPrdInfoVO().withPrdCode(prdId).build())).orElseGet(PrdInfoVO::new);
    }

    @Autowired
    private NlsRepository nlsRepository;

    @Autowired
    private LmtRepository lmtRepository;



    @Autowired
    @Qualifier("nlsApplyInfoService")
    private NlsApplyInfoService nlsApplyInfoService;

    @Autowired
    @Qualifier("pubSysInfoService")
    private PubSysInfoService pubSysInfoService;

    @Autowired
    @Qualifier("nlsProcessBizService")
    private NlsProcessBizService nlsProcessBizService;

    @Autowired
    @Qualifier("yedUpdateLmtPrdContService")
    private UpdateLmtPrdContService yedUpdateLmtPrdContService;

    @Autowired
    @Qualifier("producerService")
    private MQProducerMessageClient producerService;

    @Autowired
    @Qualifier("ctrLoanContService")
    private CtrLoanContService ctrLoanContService;

    @Autowired
    @Qualifier("cusIndivService")
    private CusIndivService cusIndivService;


}
